/*
 * AbstractLayer.cpp
 *
 *  Created on: 2010-9-26
 *      Author: wenjian
 */

#include "AbstractLayer.h"
#include "AbstractDrawPage.h"
#include "AbstractElement.h"

using namespace std;
using namespace Thk;
namespace Ed {

  AbstractLayer::AbstractLayer(AbstractDrawPage* page, AbstractSelection* selct) : drawPage(page),
  elements(), mouseHovering(false), mLeaveEvent(MouseEvent::LeaveType, this), mEnterEvent(MouseEvent::EnterType, this),
  mouseEventMode(MEventMode_Hovering),
  mouseHoveringElement(NULL), manualModeElement(NULL), selection(selct),focusElement(NULL),
  modifiedEvent(this), drawMode(DrawMode_Region), eventEnabled(true), paintEvent(this),
  drawedCount(0), spendTime(0){

    //selection->setLayer(this);
    //setDrawPage(page);
    elements.setLayer(this);
  }

  AbstractLayer::~AbstractLayer() {

  }

  /**
   * 返回宽度
   */
  real AbstractLayer::width() const {
    return drawPage->width();
  }
  /**
   * 返回高度
   */
  real AbstractLayer::height() const {
    return drawPage->height();
  }

  /**
   * 设置图层被修改状态
   */
  void AbstractLayer::setModified(bool b) {
    ModifiedSupport::setModified(b);
    //处理事件方法
    event(&modifiedEvent);
    //同步发送事件
    EventDispatcher::fire(&modifiedEvent);
  }

  bool AbstractLayer::handle(const Event* e) {
    //处理层内元素的Modified状态被修改事件
    if (e->getType() == ModifiedEvent::Type) {
      const ModifiedEvent* me = (const ModifiedEvent*) e;
      if (me->getModifiedSupport()->isModified()) {
        //设置层被修改标记
        setModified(true);
        return true;
      }
    }
    return false;
  }

  /**
   * 加入元素, 也可用于调整元素位置
   */
  void AbstractLayer::addElement(AbstractElement* e, int pos) {
    if(!e){
      return;
    }
    if(elements.contains(e)){
      //改变位置
      elements.add(e, pos);
      //设置层被修改状态
      setModified(true);
    }else{
      if(elements.add(e, pos)){
        e->setLayer(this);
        //向元素加入ModifiedEvent事件监听器, 监听元素的Modified状态
        e->addListener(ModifiedEvent::Type, this);
        //向元素加入SelectEvent事件监听器
        e->addListener(SelectEvent::Type, selection);
        //设置层被修改状态
        setModified(true);
      }
    }
  }

  /**
   * 调整元素位置,target为目标参照元素，indexBy小于等于0，调整到在目标元素之前
   * （底层方向），大于0调整到目标元素之后(顶层方向), 如果不指定目标参照元素，默认为自己
   */
  void AbstractLayer::adjustElement(AbstractElement* e, int indexBy, AbstractElement* target) {
    if(!elements.contains(e)){
      return;
    }
    int newIndex = indexBy;
    target = target?target:e;
    int idx = elements.getIndex(target);
    if(idx!=-1){
      newIndex = idx+indexBy;
    }
    addElement(e, newIndex);
  }

  /**
   * 移除元素
   */
  bool AbstractLayer::removeElement(AbstractElement* e) {
    elements.remove(e);
    //鼠标事件响应元素
    if(e == mouseHoveringElement){
      mouseHoveringElement = NULL;
    }
    //当前焦点元素
    if(focusElement == e){
      focusElement = NULL;
    }
    //移除监听器
    e->removeListener(this);
    e->removeListener(selection);
    //设置层被修改状态
    setModified(true);
    return true;
  }

  /**
   * 对ordereds中中元素排序，排序规则与元素在层中的顺序一致
   */
  void AbstractLayer::sortElements(vector<AbstractElement*>* ordereds){
    if(ordereds->empty()){
      return;
    }
    vector<AbstractElement*> tmpOrdereds;
    tmpOrdereds.insert(tmpOrdereds.begin(), ordereds->begin(),  ordereds->end());
    sort(tmpOrdereds.begin(), tmpOrdereds.end());
    std::vector<AbstractElement*>::iterator beginit = tmpOrdereds.begin();
    std::vector<AbstractElement*>::iterator endit = tmpOrdereds.end();
    ordereds->clear();
    const std::vector<AbstractElement*>* allEls = elements.getAbstractElements();
    std::vector<AbstractElement*>::const_iterator allit = allEls->begin();
    for(; allit!=allEls->end(); allit++){
      if(binary_search(beginit, endit, *allit)){
        ordereds->push_back(*allit);
      }
    }
  }

  /**
   * 在outOrdereds中返回inOrdereds被排序后的元素，排序规则与元素在层中的顺序一致
   */
  void AbstractLayer::sortElements(vector<AbstractElement*>* outOrdereds, const vector<AbstractElement*>* inOrdereds){
    if(inOrdereds->empty()){
      return;
    }
    vector<AbstractElement*> tmpOrdereds;
    tmpOrdereds.insert(tmpOrdereds.begin(), inOrdereds->begin(),  inOrdereds->end());
    sort(tmpOrdereds.begin(), tmpOrdereds.end());
    std::vector<AbstractElement*>::iterator beginit = tmpOrdereds.begin();
    std::vector<AbstractElement*>::iterator endit = tmpOrdereds.end();
    const std::vector<AbstractElement*>* allEls = elements.getAbstractElements();
    std::vector<AbstractElement*>::const_iterator allit = allEls->begin();
    for(; allit!=allEls->end(); allit++){
      if(binary_search(beginit, endit, *allit)){
        outOrdereds->push_back(*allit);
      }
    }
  }


  /**
   * 返回指定坐标 x,y上的最顶层可视元素, 如果没有，返回NULL
   *
   * @param x X坐标
   * @param y Y坐标
   * @param excluded 被排除的元素
   *
   */
  AbstractElement* AbstractLayer::find(real x, real y, const AbstractElement* excluded) {
    const std::vector<AbstractElement*>* els = elements.getAbstractElements();
    std::vector<AbstractElement*>::const_reverse_iterator it = els->rbegin();
    for (; it != els->rend(); it++) {
      AbstractElement* e = *it;
      if (e != excluded && e->isVisible() && e->intersects(x, y)) {
        return e;
      }
    }
    return NULL;
  }

  /**
   * 设置焦点
   */
  void  AbstractLayer::setFocus(){
    drawPage->setFocusLayer(this);
  }

  /**
   * 检查是否焦点层
   */
  bool  AbstractLayer::isFocus(){
    return drawPage->getFocusLayer() == this;
  }

  /**
   * 跟踪响应事件
   */
  bool AbstractLayer::trackEvent(const Event* e){
    if(!isEventEnabled()){
      return false;
    }

    if(MouseEvent::isMouseEvent(e)){
      //如果是鼠标事件
      return handleMouseEvent((const MouseEvent*)e);

    }else{//是键盘或其它事件      if(KeyEvent::isKeyEvent(e)){
      if(event(e)){
        return true;
      }
      //向层中当前元素下发事件
      if(focusElement && focusElement->isEventEnabled()){
        return focusElement->trackEvent(e);
      }
      return false;
    }
  }

//  /**
//    * 处理鼠标事件
//    */
//   bool AbstractLayer::handleMouseEvent(const MouseEvent* me){
//     real x = me->x();
//     real y = me->y();
//
//     //设置鼠标悬停状态
//     mouseHovering = true;
//
//     //在本层中分发鼠标事件
//     event(me);
//
//     //向层中元素转发鼠标事件
//     AbstractElement* e;
//     e = this->findByEventEnabled(x, y);
//     if(mouseHoveringElement && mouseHoveringElement != e){
//       mouseHoveringElement->mouseLeave(); //离开元素
//       //mouseLeaveElement(mouseHoveringElement);
//     }
//     if(mouseHoveringElement != e){
//       mouseHoveringElement = e;
//       mouseHoveringElement->mouseEnter();
//     }
//     if(e){
//       return elementTrackEvent(e, me);
//       //e->trackEvent(me);
//     }
//     return false;
//   }

  /**
   * 处理鼠标事件
   */
  bool AbstractLayer::handleMouseEvent(const MouseEvent* me){
    real x = me->x();
    real y = me->y();

    //设置鼠标悬停状态
    mouseHovering = true;

    //在本层中分发鼠标事件
    event(me);

    //向层中元素转发鼠标事件
    AbstractElement* e;
    const std::vector<AbstractElement*>* els;
    switch(mouseEventMode){
      case MEventMode_Hovering:
        e = this->findByEventEnabled(x, y);
        if(mouseHoveringElement && mouseHoveringElement != e){
          mouseHoveringElement->mouseLeave(); //离开元素
          //mouseLeaveElement(mouseHoveringElement);
        }
        if(mouseHoveringElement != e){
          mouseHoveringElement = e;
          mouseHoveringElement->mouseEnter();
        }
        if(e){
          return elementTrackEvent(mouseHoveringElement, me);
          //e->trackEvent(me);
        }
       break;
      case MEventMode_Top:
        els = elements.getAbstractElements();
        if(!els->empty()){
          e = (*els)[els->size()-1];
          if(e->isEventEnabled() && e->isVisible() && e->intersects(x, y)){
            if(mouseHoveringElement != e){
              mouseHoveringElement = e;
              mouseHoveringElement->mouseEnter();
            }
            //return e->trackEvent(me);
            return elementTrackEvent(mouseHoveringElement, me);
          }else if(mouseHoveringElement){
            mouseHoveringElement->mouseLeave(); //离开元素
            //mouseLeaveElement(mouseHoveringElement);
          }
        }
       break;
      case MEventMode_Manual:
        if(manualModeElement
            && manualModeElement->isEventEnabled()
            && manualModeElement->isVisible()
            && manualModeElement->intersects(x, y)){
          //return mouseHoveringElement->trackEvent(me);
          //mouseHoveringElement->trackEvent(me);
          if(mouseHoveringElement != manualModeElement){
            mouseHoveringElement = manualModeElement;
            mouseHoveringElement->mouseEnter();
          }
          return elementTrackEvent(mouseHoveringElement, me);
        }else{
          if(mouseHoveringElement){
            mouseHoveringElement->mouseLeave(); //离开元素
            //mouseLeaveElement(mouseHoveringElement);
          }
        }
    }
    return false;
  }

  /**
   * 返回指定坐标 x,y上的最顶层可视并能响应事件的元素, 如果没有，返回NULL
   *
   * @param x X坐标
   * @param y Y坐标
   * @param excluded 被排除的元素
   *
   */
  AbstractElement* AbstractLayer::findByEventEnabled(real x, real y) {
    const std::vector<AbstractElement*>* els = elements.getAbstractElements();
    std::vector<AbstractElement*>::const_reverse_iterator it = els->rbegin();
    for (; it != els->rend(); it++) {
      AbstractElement* e = *it;
      if (e->isEventEnabled() && e->isVisible() && e->intersects(x, y)) {
        return e;
      }
    }
    return NULL;
  }

  bool AbstractLayer::elementTrackEvent(AbstractElement* el, const MouseEvent* me){
    if(me->getType() == WheelEvent::Type){
      WheelEvent nme((WheelEvent&)(*me));
      nme.setX((int)(me->x()-el->x()));
      nme.setY((int)(me->y()-el->y()));
      nme.setSource(el);
      return el->trackEvent(&nme);
    }else{
      MouseEvent nme(*me);
      nme.setX((int)(me->x()-el->x()));
      nme.setY((int)(me->y()-el->y()));
      nme.setSource(el);
      return el->trackEvent(&nme);
    }
  }

  /**
   * 发送离开层事件
   */
  bool AbstractLayer::mouseLeave(){
    if(!mouseHovering){
      return true;
    }
    //清除鼠标悬停状态
    if(drawPage->getMouseHoveringLayer() == this){
      mouseHovering = false;
      //drawPage->mouseHoveringLayer = NULL;
      drawPage->clearMouseHoveringLayer();
    }

    //如果鼠标最近一次悬停的元素存在，调用离开元素方法
    if(mouseHoveringElement && mouseHoveringElement->mouseIsHovering() ){
      mouseHoveringElement->mouseLeave();
      //mouseLeaveElement(mouseHoveringElement);
    }
    //向在此层上监听的对象发送鼠标离开事件
    return event(&mLeaveEvent);
  }

  /**
   * 发送鼠标进入层事件
   */
  bool AbstractLayer::mouseEnter(){
    return event(&mEnterEvent);
  }

  /**
   * 调用e的throwPaintEvent方法抛出PaintEvent事件
   */
  void AbstractLayer::throwPaintEvent(AbstractElement* e){
    e->throwPaintEvent();
  }

//  /**
//   * 鼠标离开元素
//   */
//  void AbstractLayer::mouseLeaveElement(AbstractElement* e){
//    e->mouseLeave();
//  }

}
